package com.oig.sys.base.app.impl;

import cn.hutool.core.util.NumberUtil;
import com.oig.common.constants.CommonEnum;
import com.oig.common.module.SysPageInfo;
import com.oig.common.module.SysRequest;
import com.oig.common.util.JsonUtil;
import com.oig.sys.base.app.IAppHsGoodsService;
import com.oig.sys.base.app.spider.GwHsCodePageProcessor;
import com.oig.sys.base.app.spider.GwHsCodePipeline;
import com.oig.sys.base.constants.GoodsEnums;
import com.oig.sys.base.constants.SysBaseEnum;
import com.oig.sys.base.dto.CountryDto;
import com.oig.sys.base.dto.HsGoodsDto;
import com.oig.sys.base.dto.HsGoodsTariffDto;
import com.oig.sys.base.dto.HsTariffAgreementDto;
import com.oig.sys.base.entity.TbHsTariffExg;
import com.oig.sys.base.msg.IDepMqMsgService;
import com.oig.sys.base.service.ITbCountryGroupService;
import com.oig.sys.base.service.ITbCountryService;
import com.oig.sys.base.service.ITbHsGoodsService;
import com.oig.sys.base.service.ITbHsGoodsTariffService;
import com.oig.sys.base.service.ITbHsTariffAgreementService;
import com.oig.sys.base.service.ITbHsTariffExgService;
import com.oig.sys.base.tax.dto.AgreementCountry;
import com.oig.sys.base.tax.dto.GoodsTariffRate;
import com.oig.sys.base.tax.dto.GoodsVatRate;
import com.oig.sys.base.tax.dto.TariffAgreement;
import com.oig.sys.base.tax.service.IGovGoodsTaxService;
import com.oig.sys.base.vo.CountryGroupVo;
import com.oig.sys.base.vo.CountryVo;
import com.oig.sys.base.vo.HsGoodsVo;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import us.codecraft.webmagic.Spider;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Component
@Slf4j
@RequiredArgsConstructor
public class AppHsGoodsServiceImpl implements IAppHsGoodsService {

    private final ITbHsGoodsService hsGoodsService;
    private final ITbHsGoodsTariffService hsGoodsTariffService;
    private final ITbHsTariffAgreementService hsTariffAgreementService;
    private final ITbHsTariffExgService hsTariffExgService;
    private final ITbCountryGroupService countryGroupService;
    private final ITbCountryService countryService;
    private final IDepMqMsgService depMqMsgService;
    private final IGovGoodsTaxService govGoodsTaxService;

    @GlobalTransactional
    @Override
    public HsGoodsVo addHsGoods(HsGoodsDto hsGoodsDto){
        HsGoodsVo hsGoodsVo = hsGoodsService.addHsGoods(hsGoodsDto);
        // 推送mq
        this.sendMsg(hsGoodsVo);
        return hsGoodsVo;
    }

    @GlobalTransactional
    @Override
    public HsGoodsVo updateHsGoods(HsGoodsDto hsGoodsDto){
        HsGoodsVo hsGoodsVo = hsGoodsService.updateHsGoods(hsGoodsDto);
        // 推送mq
        this.sendMsg(hsGoodsVo);
        return hsGoodsVo;
    }

    @GlobalTransactional
    @Override
    public void cancelHsGoods(String hsCode){
        HsGoodsVo hsGoodsVo = hsGoodsService.cancelHsGoods(hsCode);
        // 推送mq
        this.sendMsg(hsGoodsVo);
    }

    @Override
    public HsGoodsVo getHsGoods(String hsCode){
        return hsGoodsService.getHsGoods(hsCode);
    }

    @Override
    public SysPageInfo<HsGoodsVo> listHsGoods(SysRequest<HsGoodsDto> hsGoodsDtoSysRequest){
        return hsGoodsService.listHsGoods(hsGoodsDtoSysRequest);
    }

    @Override
    public String getName(String hsCode){
        return hsGoodsService.getName(hsCode);
    }

    /**
     *
     */
    @Override
    public void startSpider(String hsCode) {
        log.info("start spider...{}", hsCode);
        //1、基础税率更新
        HsGoodsVo hsGoodsVo = this.updateBaseRate(hsCode);
        if (hsGoodsVo==null) return;
        //2、获取协定税率
        this.updateTariffAgreement(hsGoodsVo);
        // 推送mq
        this.sendMsg(hsGoodsVo);
    }

    private HsGoodsVo updateBaseRate(String hsCode){
        //1、获取基础税率
        GoodsTariffRate goodsTariffRate = govGoodsTaxService.getGoodsTariffRate(hsCode);
        log.debug("base tax-----{}", goodsTariffRate);
        if (goodsTariffRate==null){
            log.warn("未查到基础关税");
            this.hsGoodsService.cancelHsGoods(hsCode);
            return null;
        }
        //1、1、处理基础税率
        HsGoodsDto hsGoodsDto = new HsGoodsDto();
        hsGoodsDto.setHsCode(hsCode);
        hsGoodsDto.setName(goodsTariffRate.getGName());
        String trfPx = "元/", perPx="%";
        if (StringUtils.isNotBlank(goodsTariffRate.getImpDiscountRate())) {//最惠国关税
            if (goodsTariffRate.getImpDiscountRate().indexOf(trfPx)>0){ //最惠国关税
                hsGoodsDto.setTariffType(GoodsEnums.TariffType.WEIGHT.getCode());
                String hsYTaxNum = goodsTariffRate.getImpDiscountRate().trim().substring(0,goodsTariffRate.getImpDiscountRate().indexOf(trfPx));
                if (NumberUtil.isNumber(hsYTaxNum)) hsGoodsDto.setOffTariffRate(new BigDecimal(hsYTaxNum).multiply(new BigDecimal(100)));
            } else if (goodsTariffRate.getImpDiscountRate().indexOf(perPx)>0){
                hsGoodsDto.setTariffType(GoodsEnums.TariffType.PRICE.getCode());
                String hsYTaxNum = goodsTariffRate.getImpDiscountRate().trim().substring(0,goodsTariffRate.getImpDiscountRate().indexOf(perPx));
                if (NumberUtil.isNumber(hsYTaxNum)) hsGoodsDto.setOffTariffRate(new BigDecimal(hsYTaxNum));
            } else {
                hsGoodsDto.setTariffType(GoodsEnums.TariffType.PRICE.getCode());
                hsGoodsDto.setOffTariffRate(BigDecimal.ZERO);
            }
        }
        if (hsGoodsDto.getTariffType()==null){
            log.warn("关税无法解析");
            return null;
        }
        if (StringUtils.isNotBlank(goodsTariffRate.getImpOrdinaryRate())){//进口普通税率
            if (goodsTariffRate.getImpOrdinaryRate().indexOf(trfPx)>0){
                String commTariffRateNum = goodsTariffRate.getImpOrdinaryRate().trim().substring(0,goodsTariffRate.getImpOrdinaryRate().indexOf(trfPx));
                if (NumberUtil.isNumber(commTariffRateNum)) hsGoodsDto.setCommTariffRate(new BigDecimal(commTariffRateNum).multiply(new BigDecimal(100)));
            } else if (goodsTariffRate.getImpOrdinaryRate().indexOf(perPx)>0){
                String commTariffRateNum = goodsTariffRate.getImpOrdinaryRate().trim().substring(0,goodsTariffRate.getImpOrdinaryRate().indexOf(perPx));
                if (NumberUtil.isNumber(commTariffRateNum)) hsGoodsDto.setCommTariffRate(new BigDecimal(commTariffRateNum));
            } else {
                hsGoodsDto.setCommTariffRate(BigDecimal.ZERO);
            }
        }
        if (StringUtils.isNotBlank(goodsTariffRate.getImpTempRate())){    //暂定关税
            if (goodsTariffRate.getImpTempRate().indexOf(trfPx)>0){
                String provTaxRateNum = goodsTariffRate.getImpTempRate().trim().substring(0,goodsTariffRate.getImpTempRate().indexOf(trfPx));
                if (NumberUtil.isNumber(provTaxRateNum)) hsGoodsDto.setProvTaxRate(new BigDecimal(provTaxRateNum).multiply(new BigDecimal(100)));
            } else if (goodsTariffRate.getImpTempRate().indexOf(perPx)>0){
                String provTaxRateNum = goodsTariffRate.getImpTempRate().trim().substring(0,goodsTariffRate.getImpTempRate().indexOf(perPx));
                if (NumberUtil.isNumber(provTaxRateNum)) hsGoodsDto.setProvTaxRate(new BigDecimal(provTaxRateNum));
            } else {
                hsGoodsDto.setProvTaxRate(BigDecimal.ZERO);
            }
        }
        GoodsVatRate goodsVatRate = govGoodsTaxService.getGoodsVatRate(hsCode);
        if (goodsVatRate!=null){
            if (StringUtils.isNotBlank(goodsVatRate.getImpVatRate())) {    //增值税
                String vatRateNum;
                if (goodsVatRate.getImpVatRate().indexOf(perPx)>0){
                    vatRateNum = goodsVatRate.getImpVatRate().trim().substring(0,goodsVatRate.getImpVatRate().indexOf(perPx));
                } else {
                    vatRateNum = goodsVatRate.getImpVatRate().trim();
                }
                if (NumberUtil.isNumber(vatRateNum)) hsGoodsDto.setVatRate(new BigDecimal(vatRateNum));
            }
            if (StringUtils.isNotBlank(goodsVatRate.getImpConsumeRate())) {//消费税
                String consumeRate;
                if (goodsVatRate.getImpConsumeRate().indexOf(perPx)>0){
                    consumeRate = goodsVatRate.getImpConsumeRate().trim().substring(0,goodsVatRate.getImpConsumeRate().indexOf(perPx));
                } else {
                    consumeRate = goodsVatRate.getImpConsumeRate().trim();
                }
                if (NumberUtil.isNumber(consumeRate)) hsGoodsDto.setCmpTaxRate(new BigDecimal(consumeRate));
            }
        }
        return this.hsGoodsService.updateHsGoodsTax(hsGoodsDto);
    }


    private void updateTariffAgreement(HsGoodsVo hsGoodsVo){
        List<HsGoodsTariffDto> hsGoodsTariffDtoList = new ArrayList<>();
        List<HsTariffAgreementDto> hsTariffAgreementDtoList = new ArrayList<>();
        SysRequest<CountryDto> countryRequest = new SysRequest<>(1, 500);
        CountryDto countryDto = new CountryDto();
        countryDto.setAreaType(SysBaseEnum.AreaType.COUNTRY.getCode());
        countryDto.setStatus(CommonEnum.CommonStatusEnum.OK.getCode());
        countryRequest.setParamDto(countryDto);
        List<CountryVo> countryVoList = this.countryService.findCountry(countryRequest);
        Map<String,CountryVo> countryVoMap;
        if (countryVoList!=null && !countryVoList.isEmpty()){
            countryVoMap = countryVoList.stream().collect(Collectors.toMap(CountryVo::getName, Function.identity()));
        } else {
            countryVoMap = null;
        }
        List<CountryGroupVo> countryGroupVoList = this.countryGroupService.findAllCountryGroup();
        Map<String, CountryGroupVo> countryGroupVoMap;
        if (countryGroupVoList!=null && !countryGroupVoList.isEmpty()){
            countryGroupVoMap = countryGroupVoList.stream().collect(Collectors.toMap(CountryGroupVo::getName, Function.identity()));
        } else {
            countryGroupVoMap = null;
        }
        List<TariffAgreement> agreementList = govGoodsTaxService.getTariffAgreementList(hsGoodsVo.getHsCode());
        log.debug("tariff agreement--{}",agreementList);
        if (agreementList!=null && !agreementList.isEmpty()){
            agreementList.forEach(agreement -> {
                //2.1获取协定对应国家税率
                List<AgreementCountry> agreementCountryList = govGoodsTaxService.getAgreementCountryList(hsGoodsVo.getHsCode(), agreement.getAgreementCode());
                log.debug("agreement country--{}", agreementCountryList);
                HsTariffAgreementDto hsTariffAgreementDto = new HsTariffAgreementDto();
                hsTariffAgreementDto.setHsCode(hsGoodsVo.getHsCode());
                hsTariffAgreementDto.setAgreementCode(agreement.getAgreementCode());
                hsTariffAgreementDto.setAgreementName(agreement.getAgreementName());
                hsTariffAgreementDto.setAgreementRate(agreement.getImpAgreementRate());
                //2.2协定国家税率以json形式先存储
                hsTariffAgreementDto.setAgreementCountryRate(JsonUtil.toJSONString(agreementCountryList));
                //存储协定税率
                hsTariffAgreementDtoList.add(hsTariffAgreementDto);
                //特别协定，排除商品，不平铺到国家，暂时没有好的办法直接这样判断
                if ("特别协定".equals(agreement.getAgreementName())||"特别协定2".equals(agreement.getAgreementName())){
                    log.debug("查询排除商品：hsCode:{}-agreementCode:{}",hsGoodsVo.getHsCode(), agreement.getAgreementCode());
                    List<TbHsTariffExg> hsTariffExgList = this.hsTariffExgService.findHsTariffExgList(hsGoodsVo.getHsCode(), agreement.getAgreementCode());
                    if (hsTariffExgList!=null && !hsTariffExgList.isEmpty()){
                        //hscode在排除码里，那么不用添加国家
                        log.debug("特别加关税的hscode:{},在排除商品中,不用加国家特定税款", hsGoodsVo.getHsCode());
                        return;
                    }
                }
                if (countryVoMap!=null) {
                    hsGoodsTariffDtoList.addAll(this.dealAgreementCountry(hsGoodsVo, agreement, agreementCountryList, countryVoMap, countryGroupVoMap));
                }
            });
            if (!hsTariffAgreementDtoList.isEmpty()){
                this.hsTariffAgreementService.addOrUpdateList(hsTariffAgreementDtoList);
            }
            if (!hsGoodsTariffDtoList.isEmpty()){
                this.hsGoodsTariffService.reSetAllHsGoodsTariff(hsGoodsVo.getHsCode(), hsGoodsTariffDtoList);
            }
        }
    }

    /**
     * 协定税率拆出国家
     */
    private List<HsGoodsTariffDto> dealAgreementCountry(HsGoodsVo hsGoodsVo,
                                      TariffAgreement agreement,
                                      List<AgreementCountry> agreementCountryList,
                                      Map<String,CountryVo> countryVoMap,
                                      Map<String, CountryGroupVo> countryGroupVoMap){
        //2.3 国家税率处理
        List<HsGoodsTariffDto> hsGoodsTariffDtoList = new ArrayList<>();
        List<String> countryNameList = new ArrayList<>();
        agreementCountryList.forEach(agreementCountry -> {
            if (StringUtils.isBlank(agreementCountry.getConuntryName()) || StringUtils.isBlank(agreementCountry.getImpAgreementRate())){    //关税
                log.warn("country没有税率{}--{}",agreementCountry.getConuntryName(), agreementCountry.getImpAgreementRate());
                return;
            }
            CountryVo countryVo = countryVoMap.get(agreementCountry.getConuntryName());
            if (countryVo==null && agreementCountry.getConuntryName().endsWith("国")){ //系统里的国家名称可能跟海关不一致，比如孟加拉国，系统里是孟加拉，匹配去掉国
                countryVo = countryVoMap.get(agreementCountry.getConuntryName().substring(0,agreementCountry.getConuntryName().length()-1));
            }
            log.debug("country:{}",countryVo);
            if (countryVo!=null){
                HsGoodsTariffDto hsGoodsTariffDto = this.buildHsGoodsTariffDto(hsGoodsVo, countryVo, agreement, agreementCountry);
                if (hsGoodsTariffDto==null) {
                    return;
                }
                hsGoodsTariffDtoList.add(hsGoodsTariffDto);
                countryNameList.add(countryVo.getName());
            } else if ("N".equals(agreementCountry.getConuntryName().trim())){  //如果是国家名称 N 补上组织国家 只有东盟和特惠国有这种情况，先写死
                CountryGroupVo countryGroupVo=null ;
                if ("免关税待遇措施".equals(agreement.getAgreementName())){
                    countryGroupVo = countryGroupVoMap.get("特惠国");
                    if (countryGroupVo==null || countryGroupVo.getCountryList()==null){
                        log.warn("特惠国 国别组数据不存在");
                        return;
                    }
                } else if ("中国-东盟自贸区".equals(agreement.getAgreementName())){
                    countryGroupVo = countryGroupVoMap.get("东盟");
                    if (countryGroupVo==null || countryGroupVo.getCountryList()==null){
                        log.warn("东盟 国别组数据不存在");
                        return;
                    }
                } else if ("亚太贸易协定".equals(agreement.getAgreementName())){
                    countryGroupVo = countryGroupVoMap.get("亚太");
                    if (countryGroupVo==null || countryGroupVo.getCountryList()==null){
                        log.warn("亚太 国别组数据不存在");
                        return;
                    }
                }
                if (countryGroupVo==null){
                    log.warn("国别组不存在:{}--{}",agreement.getAgreementName(), agreementCountry.getConuntryName());
                    return;
                }
                countryGroupVo.getCountryList().forEach(groupMemberVo -> {
                    if (countryNameList.contains(groupMemberVo.getName())){
                        log.debug("group country has add:{}",groupMemberVo.getName());
                        return;
                    }
                    log.debug("group country add:{}",groupMemberVo.getName());
                    CountryVo groupCountry = new CountryVo();
                    groupCountry.setName(groupMemberVo.getName());
                    groupCountry.setCode(groupMemberVo.getCode());
                    groupCountry.setApplyCode(groupMemberVo.getApplyCode());
                    HsGoodsTariffDto hsGoodsTariffDto = this.buildHsGoodsTariffDto(hsGoodsVo, groupCountry, agreement, agreementCountry);
                    if (hsGoodsTariffDto==null) {
                        return;
                    }
                    hsGoodsTariffDtoList.add(hsGoodsTariffDto);
                });
            } else {
                log.warn("国家信息不存在:{}", agreementCountry.getConuntryName());
            }
        });
        return hsGoodsTariffDtoList;
    }

    private HsGoodsTariffDto buildHsGoodsTariffDto(HsGoodsVo hsGoodsVo, CountryVo countryVo,TariffAgreement agreement, AgreementCountry agreementCountry){
        HsGoodsTariffDto hsGoodsTariffDto = new HsGoodsTariffDto();
        hsGoodsTariffDto.setHsCode(hsGoodsVo.getHsCode());
        hsGoodsTariffDto.setTariffType(hsGoodsVo.getTariffType());
        String trfPx = "元/", perPx="%";
        if (agreementCountry.getImpAgreementRate().indexOf(trfPx)>0){
            hsGoodsTariffDto.setTariffType(GoodsEnums.TariffType.WEIGHT.getCode());
            String provTaxRateNum = agreementCountry.getImpAgreementRate().trim().substring(0,agreementCountry.getImpAgreementRate().indexOf(trfPx));
            if (NumberUtil.isNumber(provTaxRateNum)) hsGoodsTariffDto.setTariffRate(new BigDecimal(provTaxRateNum).multiply(new BigDecimal(100)));
        } else if (agreementCountry.getImpAgreementRate().indexOf(perPx)>0){
            hsGoodsTariffDto.setTariffType(GoodsEnums.TariffType.PRICE.getCode());
            String provTaxRateNum = agreementCountry.getImpAgreementRate().trim().substring(0,agreementCountry.getImpAgreementRate().indexOf(perPx));
            if (NumberUtil.isNumber(provTaxRateNum)) hsGoodsTariffDto.setTariffRate(new BigDecimal(provTaxRateNum));
        } else {
            if (NumberUtil.isNumber(agreementCountry.getImpAgreementRate())){
                hsGoodsTariffDto.setTariffRate(new BigDecimal(agreementCountry.getImpAgreementRate()));
            }
        }
        if (hsGoodsTariffDto.getTariffRate()==null) {
            log.warn("税率无法解析{}--{}", agreementCountry.getConuntryName(), agreementCountry.getImpAgreementRate());
            return null;
        }
        hsGoodsTariffDto.setRemark(agreement.getAgreementName());
        hsGoodsTariffDto.setCountryCode(countryVo.getCode());
        hsGoodsTariffDto.setCountryApplyCode(countryVo.getApplyCode());
        hsGoodsTariffDto.setCountryName(countryVo.getName());
        hsGoodsTariffDto.setPriority(0);
        if ("特别协定".equals(agreement.getAgreementName())){   //暂时没有好的办法
            hsGoodsTariffDto.setPriority(1);
        } else if ("特别协定2".equals(agreement.getAgreementName())){
            hsGoodsTariffDto.setPriority(2);
        }
        return hsGoodsTariffDto;
    }

    /**
     * 只获取主表的部分数据，其实都没用了
     */
    @Override
    public void startSpider(List<String> hsCodes) {
        List<String> urlList = new ArrayList<>();
        hsCodes.stream().filter(hsCode->hsCode.length()>8).forEach((hsCode -> urlList.add("https://www.hsbianma.com/Code/"+hsCode+".html") ));
        log.debug("urlList:{}", urlList);
        String[] urls = new String[urlList.size()];
        urlList.toArray(urls);
        Spider.create(new GwHsCodePageProcessor())
                .addPipeline(new GwHsCodePipeline(hsGoodsService))
                .addUrl(urls)
                .thread(5)
                .setExitWhenComplete(true)
                .start(); //非阻塞
    }

    public void sendMsg(HsGoodsVo hsGoodsVo) {
        if(!CommonEnum.CommonStatusEnum.DEL.getCode().equals(hsGoodsVo.getStatus())){
            hsGoodsVo.setHsGoodsTariffList(hsGoodsTariffService.getHsGoodsAllTariff(hsGoodsVo.getHsCode()));
        }
        // 发送mq
        depMqMsgService.addToSendMsg(CommonEnum.RelationType.OIGX_HS_GOODS.getCode(), hsGoodsVo.getHsCode(),hsGoodsVo, 0, "系统服务");
    }


    @Override
    public List<HsGoodsVo> listInfoByHsCode(List<String> hsCodes) {
        return this.hsGoodsService.listInfoByHsCode(hsCodes);
    }
}
